package com.beta.cat.config.clickhouse;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.ClassPathMapperScanner;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import ru.yandex.clickhouse.BalancedClickhouseDataSource;
import ru.yandex.clickhouse.settings.ClickHouseProperties;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

public class ClickhouseImportRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware, ApplicationContextAware {
    private Environment env;
    private ApplicationContext applicationContext;

    @Override
    public void setEnvironment(Environment environment) {
        env = environment;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        try {
            registerBeanDefinitions(registry,
                    importingClassMetadata.getClassName() + "#Registrar0");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    void registerBeanDefinitions(BeanDefinitionRegistry registry, String beanName) throws Exception {

        ClickHouseConfiguration.ClickhouseDatasourceProperties properties = new ClickHouseConfiguration.ClickhouseDatasourceProperties();

        properties.setUrl(env.getProperty(ClickHouseConfiguration.prefix + ".url"));
        properties.setUsername(env.getProperty(ClickHouseConfiguration.prefix + ".username"));
        properties.setPassword(env.getProperty(ClickHouseConfiguration.prefix + ".password"));
        properties.setBasePackage(env.getProperty(ClickHouseConfiguration.prefix + ".basePackage"));


        if (org.apache.commons.lang3.StringUtils.isBlank(properties.getBasePackage())) {
            return;
        }
        List<Resource> mapperLocations = new ArrayList<>();
        String locations = env.getProperty(ClickHouseConfiguration.prefix + ".mapperLocations");
        if (locations != null) {
            mapperLocations = resolveMapperLocations(locations.split(","));
            properties.setMapperLocations(mapperLocations);
        }
        Properties defaults = properties.getDefaults();
        if (defaults == null) {
            defaults = new Properties();
        }
        ClickHouseProperties cp = new ClickHouseProperties(defaults);
        cp.setUser(properties.getUsername());
        cp.setPassword(properties.getPassword());

        BalancedClickhouseDataSource dataSource = new BalancedClickhouseDataSource(properties.getUrl(), cp);

        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        if (!CollectionUtils.isEmpty(properties.getMapperLocations())) {
            sessionFactory.setMapperLocations(properties.getMapperLocations().toArray(new Resource[0]));
        }
        sessionFactory.afterPropertiesSet();

        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        scanner.setAddToConfig(true);
        scanner.setSqlSessionFactory(sessionFactory.getObject());
        scanner.setResourceLoader(this.applicationContext);
        scanner.registerFilters();
        scanner.scan(
                StringUtils.tokenizeToStringArray(properties.getBasePackage(), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
    }

    /**
     * 解析出具体的文件名称
     *
     * @param mapperLocations
     * @return
     */
    private List<Resource> resolveMapperLocations(String[] mapperLocations) {
        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
        List<Resource> resources = new ArrayList<Resource>();
        if (mapperLocations != null) {
            for (String mapperLocation : mapperLocations) {
                if (!StringUtils.hasText(mapperLocation)) {
                    continue;
                }
                try {
                    Resource[] mappers = resourceResolver.getResources(mapperLocation);
                    resources.addAll(Arrays.asList(mappers));
                } catch (IOException e) {
                    // ignore
                }
            }
        }
        return resources;
    }
}
